package com.xxxtea.config.converter;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * MyBatis-List类型处理器
 * 
 * 用于将List<T>类型与数据库VARCHAR字段进行相互转换。
 * 支持以逗号分隔的字符串与List的互转，适用于字符串和整型的自动识别。
 * 
 * 主要应用于MyBatis持久化层，简化List类型字段的存取。
 * 
 * @author badman
 * @since 1.0.0
 */
@SuppressWarnings("all")
@MappedTypes({List.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ListTypeHandler<T> implements TypeHandler<List<T>> {
	/** 分隔符，默认为英文逗号 */
	private final String SPLIT = ",";

	/**
	 * 设置参数，将List转为逗号分隔字符串存入数据库
	 * 
	 * @param ps 预编译语句
	 * @param i 参数索引
	 * @param parameter 参数值
	 * @param jdbcType JDBC类型
	 * @throws SQLException SQL异常
	 */
	@Override
	public void setParameter(PreparedStatement ps, int i, List<T> parameter, JdbcType jdbcType) throws SQLException {
		if (parameter == null || parameter.isEmpty()) {
			ps.setNull(i, Types.VARCHAR);
			return;
		}
		String str = StrUtil.join(SPLIT, parameter);
		ps.setString(i, str);
	}

	/**
	 * 通过列名获取结果，将逗号分隔字符串转为List
	 */
	@Override
	public List<T> getResult(ResultSet rs, String columnName) throws SQLException {
		String str = rs.getString(columnName);
		if (StrUtil.isEmpty(str)) {
			return new ArrayList<>();
		}
		return parseStringToListAsJson(str);
	}

	/**
	 * 通过列索引获取结果，将逗号分隔字符串转为List
	 */
	@Override
	public List<T> getResult(ResultSet rs, int columnIndex) throws SQLException {
		String str = rs.getString(columnIndex);
		if (StrUtil.isEmpty(str)) {
			return new ArrayList<>();
		}
		return parseStringToListAsJson(str);
	}

	/**
	 * 通过CallableStatement获取结果，将逗号分隔字符串转为List
	 */
	@Override
	public List<T> getResult(CallableStatement cs, int columnIndex) throws SQLException {
		String str = cs.getString(columnIndex);
		if (StrUtil.isEmpty(str)) {
			return new ArrayList<>();
		}
		return parseStringToListAsJson(str);
	}

	/**
	 * 逗号分隔字符串转List，先转为JSON数组字符串再解析
	 *
	 * @param str 逗号分隔字符串
	 * @return List对象
	 */
	private List<T> parseStringToListAsJson(String str) {
		// 如果本身就是JSON数组，直接解析
		if (str.trim().startsWith("[")) {
			return JSONUtil.toList(str, Object.class).stream().map(e -> {
				try {
					return (T) Integer.valueOf(e.toString());
				} catch (NumberFormatException ex) {
					return (T) e.toString();
				}
			}).collect(Collectors.toList());
		}
		// 否则转为JSON数组字符串再解析
		String jsonArr = JSONUtil.toJsonStr(str.split(SPLIT));
		return JSONUtil.toList(jsonArr, Object.class).stream().map(e -> {
			try {
				return (T) Integer.valueOf(e.toString());
			} catch (NumberFormatException ex) {
				return (T) e.toString();
			}
		}).collect(Collectors.toList());
	}
}